package com.randi.common.utils.secret;

import com.randi.common.config.AppConfig;
import com.randi.common.enums.ResultCode;
import com.randi.common.exception.ServiceException;
import org.bouncycastle.util.encoders.Base64;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * @author ziye
 */
@Component
public class SecretUtils {

    /**
     * 加密盐
     */
    private static String SALT;

    @Resource
    private void init(AppConfig.SystemConfig.SecretConfig secretConfig) {
        SALT = secretConfig.getSalt();
    }

    /**
     * 加密
     *
     * @param str 数据
     * @return encrypted
     */
    private static String handleEncrypt(String str, String salt) {
        try {
            byte[] bytes = str.getBytes();

            Cipher instance = Cipher.getInstance("AES/CBC/NoPadding");
            SecretKeySpec aes = new SecretKeySpec(salt.getBytes(), "AES");
            IvParameterSpec ivParameterSpec = new IvParameterSpec(salt.getBytes());
            instance.init(Cipher.ENCRYPT_MODE, aes, ivParameterSpec);

            byte[] encrypted = instance.doFinal(bytes);
            return new String(Base64.encode(encrypted));
        } catch (Exception e) {
            throw new ServiceException(ResultCode.SECRET_ENCRYPT_ERROR, e.getMessage());
        }
    }

    /**
     * 加密
     *
     * @param str 数据
     * @return encrypted
     */
    public static String encrypt(String str) {
        return handleEncrypt(str, SALT);
    }

    /**
     * 加密
     *
     * @param str  数据
     * @param salt 加密盐
     * @return encrypted
     */
    public static String encrypt(String str, String salt) {
        return handleEncrypt(str, salt);
    }

    /**
     * 解密
     *
     * @param data 数据
     * @param key  key
     * @param iv   iv
     * @return decrypted
     */
    private static String handleDecrypt(String data, String key, String iv) {
        try {
            data += "==";
            byte[] encrypted = Base64.decode(data);

            Cipher instance = Cipher.getInstance("AES/CBC/NoPadding");
            SecretKeySpec aes = new SecretKeySpec(key.getBytes(), "AES");
            IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes());
            instance.init(Cipher.DECRYPT_MODE, aes, ivParameterSpec);

            byte[] bytes = instance.doFinal(encrypted);
            return new String(bytes).trim();
        } catch (Exception e) {
            throw new ServiceException(ResultCode.SECRET_DECRYPT_ERROR, e.getMessage());
        }
    }

    /**
     * 解密
     *
     * @param str 数据
     * @return decrypted
     */
    public static String decrypt(String str) {
        return handleDecrypt(str, SALT, SALT);
    }

    /**
     * 解密
     *
     * @param data 数据
     * @param salt 加密盐
     * @return decrypted
     */
    public static String decrypt(String data, String salt) {
        return handleDecrypt(data, salt, salt);
    }

    /**
     * 解密
     *
     * @param data 数据
     * @param key  key
     * @param iv   iv
     * @return decrypted
     */
    public static String decrypt(String data, String key, String iv) {
        return handleDecrypt(data, key, iv);
    }

}
